////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef __WN_TOP_LEVEL_ELEMENT_H__
#define __WN_TOP_LEVEL_ELEMENT_H__

#include "WNParseNode.h"

#include <deque>

class WNDataType;
class WNTopLevelElementList;
class WNInstructionList;
class WNInstruction;
class WNFunctionHeaderList;
struct WNFunction;

namespace llvm {
    class Value;
    class Function;
};

class WNTopLevelElement : public WNParseNode {
public:
    virtual ~WNTopLevelElement();
    WNTopLevelElement(WN_SIZE_T _startLine,
                      WN_SIZE_T _endLine,
                      WN_SIZE_T _startChar,
                      WN_SIZE_T _endChar,
                      WN_BOOL   _stackRet,
                      WNDataType* _dataType,
                      WNIdentifierElement _functionName,
                      WNInstructionList* _instructionList);
    WNTopLevelElement(WN_SIZE_T _startLine,
                       WN_SIZE_T _endLine,
                       WN_SIZE_T _startChar,
                       WN_SIZE_T _endChar,
                       WN_BOOL   _stackRet,
                       WNDataType* _dataType,
                       WNIdentifierElement _functionName,
                       WNInstructionList* _instructionList,
                       WNFunctionHeaderList* _header);
    virtual llvm::Value* OptimizeAndGenerate(WNScriptingEngineData& _scriptingData, WNFunctionDecl* _functionDecl);
    llvm::Function* OptimizeAndGenerateFunction(WNScriptingEngineData& _scriptingData, WNFunction** _fileName);
    virtual WN_BOOL ReportErrors();

private:
    WNDataType* mDataType;
    WN_BOOL  mStackRet;
    WNIdentifierElement mFunctionName;
    WNFunctionHeaderList* mFunctionHeaderList;
    WNInstructionList* mInstructionList;
    std::deque<WNInstruction*> mInstructions;
};

class WNTopLevelElementList : public WNParseNode {
public:
    ~WNTopLevelElementList();
    WNTopLevelElementList(WN_SIZE_T _startLine,
                      WN_SIZE_T _endLine,
                      WN_SIZE_T _startChar,
                      WN_SIZE_T _endChar);

    WNTopLevelElementList(WN_SIZE_T _startLine,
                      WN_SIZE_T _endLine,
                      WN_SIZE_T _startChar,
                      WN_SIZE_T _endChar,
                      WNTopLevelElement* _topLevelElement,
                      WNTopLevelElementList* _topLevelElementList);
    WNTopLevelElement* AppropriateElement(){ WNTopLevelElement * elem = mTopLevelElement; mTopLevelElement = WN_NULL; return elem; }
    WNTopLevelElementList* AppropriateElementList() { WNTopLevelElementList * elem = mTopLevelElementList; mTopLevelElementList = WN_NULL; return elem; }
    virtual llvm::Value* OptimizeAndGenerate(WNScriptingEngineData& scriptingData, WNFunctionDecl* functionDecl);

private:
    WNTopLevelElement* mTopLevelElement;
    WNTopLevelElementList* mTopLevelElementList;
};

#endif // __WN_TOP_LEVEL_ELEMENT_H__